package cn.openea.perpartner.meily.web.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.HashUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import cn.openea.perpartner.common.core.constant.Constants;
import cn.openea.perpartner.common.core.exception.ServiceException;
import cn.openea.perpartner.common.core.manager.AsyncManager;
import cn.openea.perpartner.common.core.text.Convert;
import cn.openea.perpartner.common.core.utils.Arith;
import cn.openea.perpartner.common.core.utils.StringUtils;
import cn.openea.perpartner.common.core.web.domain.AjaxResult;
import cn.openea.perpartner.common.redis.service.RedisCache;
import cn.openea.perpartner.meily.behavioral.entity.BehavioralData;
import cn.openea.perpartner.meily.behavioral.service.IBehavioralDataService;
import cn.openea.perpartner.meily.constant.CommonConstants;
import cn.openea.perpartner.meily.constant.enums.GoodsTypeEnums;
import cn.openea.perpartner.meily.rabbit.domain.DelayDto;
import cn.openea.perpartner.meily.rabbit.factory.DelayServiceFactory;
import cn.openea.perpartner.meily.rabbit.service.DelayService;
import cn.openea.perpartner.meily.rabbit.service.impl.PublisherService;
import cn.openea.perpartner.meily.util.UserContext;
import cn.openea.perpartner.meily.web.entity.Goods;
import cn.openea.perpartner.meily.web.entity.vo.GoodsVo;
import cn.openea.perpartner.meily.web.mapper.GoodsMapper;
import cn.openea.perpartner.meily.web.service.IBuyingRecordService;
import cn.openea.perpartner.meily.web.service.IGoodsService;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * (Goods)表服务实现类
 *
 * @author Weird077
 * @since 2023-01-11 21:04:18
 */
@Slf4j
@Service("goodsService")
public class GoodsServiceImpl extends ServiceImpl<GoodsMapper, Goods> implements IGoodsService {
    @Autowired
    private PublisherService publisher;
    @Value("${rabbit.default.beanName}")
    private String defaultBeanName;


    @Autowired
    private IBuyingRecordService buyingRecordService;
    @Resource
    private RedisCache redisCache;
    @Resource
    private IBehavioralDataService behavioralDataService;

    @Override
    public List<Goods> selectList(GoodsVo vo) {
        return baseMapper.selectList(buildGoodsWrapper(vo, true));
    }

    @Override
    public Map<String, Object> goodsStatistics(GoodsVo vo) {
        return baseMapper.countGoodsTypeNum(buildGoodsWrapper(vo, false));
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public String batchCopyGoods(List<Long> idList) {
        int successNum = 0;
        int failureNum = 0;
        StringBuilder successMsg = new StringBuilder();
        StringBuilder failureMsg = new StringBuilder();
        LambdaQueryWrapper<Goods> wrapper = new LambdaQueryWrapper<>();
        wrapper.in(Goods::getGoodsId, idList);
        List<Goods> goodsList = list(wrapper);
        for (int i = goodsList.size() - 1; i >= 0; i--) {
            Goods goods = goodsList.get(i);
            long result = count(Wrappers.lambdaQuery(Goods.class)
                    .eq(Goods::getGoodsNo, goods.getGoodsNo())
                    .eq(Goods::getGoodsType, "SUMMER"));
            if (result > 0) {
                goodsList.remove(goods);
                failureNum++;
                failureMsg.append("<br/>").append(failureNum).append("、商品 ").append(goods.getGoodsName()).append(" 已存在活动中");
            }
        }
        if (failureNum > 0) {
            failureMsg.insert(0, "共 " + failureNum + " 个商品添加失败，如下：");
        }
        if (!goodsList.isEmpty()) {
            List<Goods> productList = new ArrayList<>();
            for (Goods goods : goodsList) {
                goods.setGoodsType("SUMMER");
                goods.setGoodsId(null);
                goods.setGoodsNo(StringUtils.getDigitalCoding(18, "HW"));
                goods.setStatus("已下架");
                goods.setCreateTime(DateUtil.now());
                goods.setUpdateTime(DateUtil.now());
                goods.setCreateUser(UserContext.getUserId());
                goods.setUpdateUser(UserContext.getUserId());
                productList.add(goods);
                successNum++;
                successMsg.append("<br/>").append(successNum).append("、商品 ").append(goods.getGoodsName()).append(" 加入活动库成功");
            }
            saveBatch(productList);
            successMsg.insert(0, "共 " + successNum + " 个商品添加到'夏日爆款'活动成功，如需修改，请前往活动库配置。数据如下：");
        }
        return successMsg.append("<br/>").append(failureMsg).toString();
    }

    public LambdaQueryWrapper<Goods> buildGoodsWrapper(GoodsVo vo, boolean isSort) {
        LambdaQueryWrapper<Goods> wrapper = new LambdaQueryWrapper<>();
        GoodsTypeEnums goodsType = vo.getGoodsType();
        if (goodsType != null) {
            wrapper.eq(Goods::getGoodsType, goodsType.name());
        }
        if (StrUtil.isNotBlank(vo.getStatus())) {
            wrapper = "已上架".equals(vo.getStatus()) ? wrapper.eq(Goods::getStatus, vo.getStatus())
                    : wrapper.and(wrap -> {
                wrap.eq(Goods::getStatus, vo.getStatus()).or()
                        .eq(Goods::getStatus, "");

            });
        }
        if (StrUtil.isNotBlank(vo.getBrand())) {
            wrapper.eq(Goods::getBrand, vo.getBrand());
        }
        if (StrUtil.isNotBlank(vo.getEnterpriseNo())) {
            wrapper.eq(Goods::getEnterpriseNo, vo.getEnterpriseNo());
        }
        if (StrUtil.isNotBlank(vo.getGoodsName())) {
            wrapper.like(Goods::getGoodsName, vo.getGoodsName());
        }
        if (StrUtil.isNotBlank(vo.getCategory())) {
            wrapper.like(Goods::getCategory, vo.getCategory());
        }
        if (StrUtil.isNotBlank(vo.getGoodsNo())) {
            wrapper.like(Goods::getGoodsNo, vo.getGoodsNo());
        }
        String dateRange = vo.getDateRange();
        if (JSONUtil.isJson(dateRange)) {
            JSONObject jsonObject = JSONObject.parseObject(dateRange);
            String startDate = jsonObject.getString("startDate");
            String endDate = jsonObject.getString("endDate");
            if (StrUtil.isNotBlank(startDate) && StrUtil.isNotBlank(endDate)) {
                // 比较两个时间的大小
                DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
                if (LocalDate.parse(startDate, formatter).isAfter(LocalDate.parse(endDate, formatter))) {
                    throw new ServiceException("结束时间不能大于开始时间");
                }
                wrapper.apply("DATE(create_time) BETWEEN '" + startDate + "' AND '" + endDate + "'");
            }
        }
        Short top = vo.getTop();
        if (top == null) {
            wrapper.orderByDesc(Goods::getGoodsTop);
        } else {
            // 是否查询只有置顶的数据
            wrapper = top == 0 ? wrapper.and(wrap -> {
                wrap.eq(Goods::getGoodsTop, "")
                        .or()
                        .isNull(Goods::getGoodsTop);
            }) : wrapper.and(wrap -> {
                wrap.ne(Goods::getGoodsTop, "")
                        .isNotNull(Goods::getGoodsTop);
            });

        }
        if (isSort) {
            wrapper.orderByDesc(Goods::getGoodsTop);
            wrapper.orderByDesc(Goods::getReleaseTime);
            wrapper.orderByAsc(Goods::getCreateTime);
        }
        return wrapper;
    }

    @Override
    public boolean top(Long goodsId) {
        // 需要根据类型区分
        Goods goods = Optional.ofNullable(baseMapper.selectById(goodsId))
                .orElseThrow(() -> new ServiceException("商品不存在"));

        LambdaQueryWrapper<Goods> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Goods::getGoodsType, goods.getGoodsType());
        wrapper.orderByDesc(Goods::getGoodsTop);
        wrapper.last("limit 1");
        Goods topGoods = this.getOne(wrapper);
        if (BeanUtil.isEmpty(topGoods)) {
            topGoods.setGoodsTop("0");
        }
        if (StrUtil.isEmpty(topGoods.getGoodsTop())) {
            topGoods.setGoodsTop("0");
        }
        int sort = Convert.toInt(topGoods.getGoodsTop());
        sort++;
        String goodsTop = Convert.toStr(sort);
        if (goodsTop.length() == 1) {
            // 单位数 前面补0
            goodsTop = "0" + goodsTop;
        }
        /**
         * 更改必须从sql 去改，mp会默认调用类的get方法
         */
        return baseMapper.topGoods(goodsId, goodsTop, UserContext.getUserId()) > 0;
    }

    @Override
    public boolean topCancel(Long goodsId) {
        return baseMapper.cancelTopGoods(goodsId, UserContext.getUserId()) > 0;
    }

    @Override
    public String selectCount(GoodsVo vo) {
        LambdaQueryWrapper<Goods> wrapper = new LambdaQueryWrapper<>();
        GoodsTypeEnums goodsType = vo.getGoodsType();
        if (goodsType != null) {
            wrapper.eq(Goods::getGoodsType, goodsType.name());
        }
        if (StrUtil.isNotBlank(vo.getStatus())) {
            wrapper.eq(Goods::getStatus, vo.getStatus());
        }
        return Convert.toStr(count(wrapper));
    }

    @Override
    public Goods findByGoodsNo(String goodsNo) {
        LambdaQueryWrapper<Goods> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Goods::getGoodsNo, goodsNo);
        return getOne(wrapper, false);
    }

    @Override
    public Goods queryDetails(String goodsNo, String goodsId) {
        LambdaQueryWrapper<Goods> wrapper = new LambdaQueryWrapper<>();
        if (StrUtil.isNotBlank(goodsNo)) {
            wrapper.eq(Goods::getGoodsNo, goodsNo);
        }
        if (StrUtil.isNotBlank(goodsId)) {
            wrapper.eq(Goods::getGoodsId, goodsId);
        }
        return getOne(wrapper, false);
    }

    @Override
    public List<Goods> queryAll(GoodsVo goodsVo) {
        LambdaQueryWrapper<Goods> wrapper = new LambdaQueryWrapper<>();
        // 只查询上架的商品
        wrapper.eq(Goods::getStatus, "已上架");
        // 商品类型
        GoodsTypeEnums goodsType = goodsVo.getGoodsType();
        if (goodsType != null) {
            wrapper.eq(Goods::getGoodsType, goodsType.name());
        }
        // 根据供应链分类查询
        if (StrUtil.isNotBlank(goodsVo.getSupplyChain())) {
            wrapper.like(Goods::getSupplyChain, goodsVo.getSupplyChain());
        }
        if (StrUtil.isNotBlank(goodsVo.getSearchStr())) {
            //若商品分类为空，模糊查询时，需要包括supplyChain字段，否则不需要
            if (StrUtil.isBlank(goodsVo.getSupplyChain())) {
                wrapper.and(wrap -> wrap.like(Goods::getGoodsNo, goodsVo.getSearchStr())
                        .or().like(Goods::getGoodsName, goodsVo.getSearchStr())
                        .or().like(Goods::getDetail, goodsVo.getSearchStr())
                        .or().like(Goods::getSupplyChain, goodsVo.getSearchStr())
                        .or().like(Goods::getGoodsTag, goodsVo.getSearchStr())
                        .or().like(Goods::getBrand, goodsVo.getSearchStr()));
            } else {
                wrapper.and(wrap -> wrap.like(Goods::getGoodsNo, goodsVo.getSearchStr())
                        .or().like(Goods::getGoodsName, goodsVo.getSearchStr())
                        .or().like(Goods::getDetail, goodsVo.getSearchStr())
                        .or().like(Goods::getGoodsTag, goodsVo.getSearchStr())
                        .or().like(Goods::getBrand, goodsVo.getSearchStr()));
            }
        }
        Short top = goodsVo.getTop();
        if (top == null) {
            wrapper.orderByDesc(Goods::getGoodsTop);
        } else {
            // 是否查询只有置顶的数据
            wrapper = top == 0 ? wrapper.and(wrap -> {
                wrap.eq(Goods::getGoodsTop, "")
                        .or()
                        .isNull(Goods::getGoodsTop);
            }) : wrapper.and(wrap -> {
                wrap.ne(Goods::getGoodsTop, "")
                        .isNotNull(Goods::getGoodsTop);
            });

        }
        if (goodsVo.isExcludeZoneData()) {
            String key = goodsType != null ? goodsType.getValue() + "_" + CommonConstants.REDIS_KEY.ZONE_GOODS_ID : CommonConstants.REDIS_KEY.ZONE_GOODS_ID;
            List<Long> zoneDataIds = redisCache.getCacheObject(key);
            if (zoneDataIds != null && !zoneDataIds.isEmpty()) {
                wrapper.notIn(Goods::getGoodsId, zoneDataIds);
            }
        }
        wrapper.orderByDesc(Goods::getReleaseTime);
        wrapper.orderByAsc(Goods::getCreateTime);
        List<Goods> list = list(wrapper);
        list.forEach(item -> {
            String quantity = buyingRecordService.getGoodsSalesVolumeByGoodsNo(item.getGoodsNo());
            String customSales = item.getCustomSales();
            if (StrUtil.isEmpty(customSales)) {
                customSales = "0";
            }
            int soldNum = Convert.toInt(quantity) + Convert.toInt(customSales);
            item.setSoldNum(Convert.toStr(soldNum));
        });
        return list;
    }

    @Override
    public boolean shelf(Long goodsId) {
        Goods goods = getById(goodsId);
        goods.setStatus("已上架");
        goods.setUpdateUser(UserContext.getUserId());
        goods.setReleaseTime(DateUtil.now());
        goods.setUpdateTime(DateUtil.now());
        boolean isSuccess = updateById(goods);
        //发送消息队列
        DelayDto delay = new DelayDto();
        delay.setGoodsId(Convert.toStr(goodsId));
        delay.setCyclicId(cycle(goodsId));
        delay.setBeanName(defaultBeanName);
        //1、周期天数
        String cycle = goods.getHelpCycle();
        //2、发布时间
        DateTime releaseTime = DateUtil.parseDateTime(goods.getReleaseTime());
        //3、计算周期到期时间
        DateTime nextTime = DateUtil.offsetDay(releaseTime, Convert.toInt(cycle));
        //4、计算队列到期时间，精确到毫秒
        long delayTime = DateUtil.betweenMs(releaseTime, nextTime);
        delay.setDelayTime(delayTime);
        //5、发送消息
        publisher.execute(delay);

        /**
         * 2023-07-05 add by lys 汇集数据
         * 用于企业动态的展示（暂时不需要管数据是否插入成功）
         */
        /*上架商品
        文案：我刚上架了一款新产品，快来看看吧。
        图片：商品首图；标题：商品标题；小字：商品规格；金额：玫丽价；标签：去掉*/
        BehavioralData behavioralData = new BehavioralData();
        behavioralData.setTitle("我刚上架了一款新产品，快来看看吧。");// 文案
        behavioralData.setSubject(goods.getGoodsName());// 标题
        behavioralData.setContent(goods.getSpecification());// 内容（商品/样品规格）
        if(StrUtil.isNotBlank(goods.getGoodsImages())){
            behavioralData.setImage(goods.getGoodsImages().split(",")[0]);// 图片
        }
        behavioralData.setPrice(goods.getDiscountPrice());
        behavioralData.setLabel(goods.getGoodsTag());
        behavioralData.setType("0");// 类型。0动态；1工作；2商品；3创作
        behavioralData.setJumpUrl("/pages_private_scene2/GroupPurchase/DistributionGoods?goodsNo=" + goods.getGoodsNo() + "&goodsId=" + goods.getGoodsId());// 商品详情页面
        behavioralData.setSourceId(String.valueOf(goods.getGoodsId()));// 来源id
        behavioralData.setSourceType("5");// 来源类型。0团购；1测评；2样品；3招聘；4协作；5上架商品；6发布学习
        behavioralData.setUserId(goods.getCreateUser());
        behavioralData.setUserName("");
        behavioralData.setStatus("1");// 状态。0停用；1启用
        behavioralData.setEnterpriseNo(goods.getEnterpriseNo());// 企业编号
        behavioralData.setEnterpriseName(goods.getEnterpriseName());// 企业名称
        behavioralData.setCreateTime(DateUtil.now());
        behavioralData.setUpdateTime(DateUtil.now());
        behavioralDataService.save(behavioralData);

        return isSuccess;
    }

    @Override
    public boolean down(Long goodsId) {
        Goods goods = new Goods();
        goods.setGoodsId(goodsId);
        goods.setStatus("已下架");
        goods.setUpdateUser(UserContext.getUserId());
        goods.setUpdateTime(DateUtil.now());

        DelayService delayService = DelayServiceFactory.getHandler(defaultBeanName);
        //5、执行延时处理类的业务逻辑
        AsyncManager.me().execute(delayService.execute(DelayDto.builder()
                .goodsId(Convert.toStr(goodsId))
                .cyclicId(cycle(goodsId))
                .build()));
        return updateById(goods);
    }

    @Override
    public String cycle(Long goodsId) {
        Goods goods = getById(goodsId);
        if (BeanUtil.isNotEmpty(goods) && "已上架".equals(goods.getStatus())) {
            //1、取周期天数
            String cycle = goods.getHelpCycle();
            //2、取发布时间
            String releaseTime = goods.getReleaseTime();
            if (StrUtil.isBlank(releaseTime)) {
                releaseTime = goods.getUpdateTime();
            }
            //3、取发布时间年份
            StringBuilder character = new StringBuilder(releaseTime.substring(2, 4));
            Date releaseDate = DateUtil.parseDateTime(releaseTime);
            String currentTime = DateUtil.now();
            Date nowDate = DateUtil.parseDateTime(currentTime);
            //4、计算当前时间与发布时间的差值（精确到分）
            long betweenMinutes = DateUtil.between(releaseDate, nowDate, DateUnit.MINUTE);
            //5、周期天数转换为分钟数
            long cycleMinutes = Convert.toLong(cycle) * 24 * 60;
            //6、计算周期数，当前时间和发布时间的差值除以周期分钟数，向上取整即为当前期数
            int num = (int) Math.ceil(Arith.div(betweenMinutes, cycleMinutes));
            if (num > 10 && num < 100) {
                character.append("0");
            } else {
                character.append("00");
            }
            character.append(num);
            character.append("-");
            //7、拼接商品id
            character.append(Convert.toStr(goodsId));
            character.append("-");
            //8、计算发布时间哈希值
            int hash = HashUtil.fnvHash(releaseTime);
            character.append(Convert.toStr(hash));
            return character.toString();
        }
        return "0";

    }

    @Override
    public List<Goods> similar(GoodsVo goodsVo) {
        LambdaQueryWrapper<Goods> wrapper = new LambdaQueryWrapper<>();
        wrapper.ne(Goods::getBrand, "");
        wrapper.eq(Goods::getCategory, goodsVo.getCategory());
        wrapper.orderByDesc(Goods::getBrand);
        wrapper.orderByDesc(Goods::getCategory);
        wrapper.last("limit 10");
        return list(wrapper);
    }


    /**
     * 重新计算当帮卖数
     *
     * @param dataStr 商品的录入时间非更新时间
     * @param idname  可以是商品名称，也可以是商品的id号，即一个固定的值
     * @param num     当前商品的真实帮卖数
     * @return 按算法扩容后的帮卖数
     */
    private int calcNum(String dataStr, String idname, int num) {
        long nowtime = System.currentTimeMillis();
        long diffday = 1;
        if (StrUtil.isNotBlank(dataStr)) {
            Date date = DateUtil.parseDate(dataStr);
            if (date != null && date.getTime() > 86400000L) {
                diffday = Math.abs(nowtime - date.getTime()) / 86400000L;
            }
        }
        if (diffday == 0) {
            return 0;
        }
        // 增幅因子，即商品默认是从0-17的数，取hash的绝对值
        int n1 = Math.abs(idname.hashCode()) % 18;
        n1 = n1 == 0 ? 2 : n1;
        if (diffday == 1) {
            return (n1 + num + 1);
        }
        return (int) ((n1 + num) * diffday + (n1 + num + diffday) * 2 / n1);
    }

    @Override
    public Goods findById(String goodsId) {
        return baseMapper.selectById(goodsId);
    }

    @Override
    public List<Goods> selectProductList(GoodsVo vo) {
        LambdaQueryWrapper<Goods> wrapper = new LambdaQueryWrapper<>();
        GoodsTypeEnums goodsType = vo.getGoodsType();
        if (goodsType != null) {
            wrapper.eq(Goods::getGoodsType, goodsType.name());
        }
        if (StrUtil.isNotBlank(vo.getActivityType())) {
            wrapper.apply("not exists (select 1 from meily_activity_products map where meily_goods.goods_no = map.goods_no)");
        } else {
            wrapper.apply("not exists (select 1 from meily_goods map where meily_goods.goods_no = map.goods_no  and map.goods_type = 'SUMMER')");
        }
        if (StrUtil.isNotBlank(vo.getStatus())) {
            wrapper.eq(Goods::getStatus, vo.getStatus());
        }
        if (StrUtil.isNotBlank(vo.getBrand())) {
            wrapper.eq(Goods::getBrand, vo.getBrand());
        }
        if (StrUtil.isNotBlank(vo.getGoodsName())) {
            wrapper.like(Goods::getGoodsName, vo.getGoodsName());
        }
        if (StrUtil.isNotBlank(vo.getCategory())) {
            wrapper.like(Goods::getCategory, vo.getCategory());
        }
        String dateRange = vo.getDateRange();
        if (JSONUtil.isJson(dateRange)) {
            JSONObject jsonObject = JSON.parseObject(dateRange);
            String startDate = jsonObject.getString("startDate");
            String endDate = jsonObject.getString("endDate");
            if (StrUtil.isNotBlank(startDate) && StrUtil.isNotBlank(endDate)) {
                // 比较两个时间的大小
                DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
                if (LocalDate.parse(startDate, formatter).isAfter(LocalDate.parse(endDate, formatter))) {
                    throw new ServiceException("结束时间不能大于开始时间");
                }
                wrapper.apply("DATE(create_time) BETWEEN '" + startDate + "' AND '" + endDate + "'");
            }
        }
        wrapper.orderByDesc(Goods::getGoodsTop);
        wrapper.orderByDesc(Goods::getUpdateTime);
        return list(wrapper);
    }

    /**
     * 从商品表查询商品分类
     *
     * @param type 商品类型
     * @return 商品分类
     */
    @Override
    public List<JSONObject> selectProductCategory(String type) {
        String redisKey = Constants.MERRY_CONFIG_KEY + type;
        List<JSONObject> typeArray = redisCache.getCacheList(redisKey);
        if (typeArray.isEmpty()) {
            //1、查询所有商品的分类
            LambdaQueryWrapper<Goods> wrapper = Wrappers.<Goods>lambdaQuery()
                    .select(Goods::getCategory).eq(Goods::getGoodsType, type)
                    .ne(Goods::getCategory, "").isNotNull(Goods::getCategory);
            List<Goods> goodsList = list(wrapper);
            //2、将分类进行分组
            List<String> typeList = goodsList.stream().map(goods -> StrUtil.split(goods.getCategory(), "-")[0])
                    .collect(Collectors.toList());
            //3、去除空值
            typeList.removeIf(StrUtil::isBlank);
            //4、统计每个分类的数量
            JSONObject typeObj = new JSONObject();
            typeList.forEach(typeStr -> {
                if (typeObj.containsKey(typeStr)) {
                    typeObj.put(typeStr, typeObj.getInteger(typeStr) + 1);
                } else {
                    typeObj.put(typeStr, 1);
                }
            });
            //5、将分类和数量转换为json数组
            typeObj.forEach((key, value) -> {
                JSONObject object = new JSONObject();
                object.put("name", key);
                object.put("value", value);
                typeArray.add(object);
            });
            //6、对json数组进行排序
            typeArray.sort(Comparator.comparing(obj -> ((JSONObject) obj).getInteger("value")).reversed());
            typeArray.forEach(obj -> obj.remove("value"));
            redisCache.setCacheList(redisKey, typeArray);
            redisCache.expire(redisKey, 24, TimeUnit.HOURS);
        }
        return typeArray;
    }

    @Override
    public Map<String, List<Goods>> queryZoneShowGoods(GoodsTypeEnums goodsTypeEnums) {
        List<Long> zoneGoodsIds = new ArrayList<>();
        List<GoodsTypeEnums> values = new ArrayList<>();
        if (goodsTypeEnums == null) {
            values = Arrays.asList(GoodsTypeEnums.values().clone());
        } else {
            values.add(goodsTypeEnums);
        }
        Map<String, List<Goods>> zoneGoods = new HashMap<>(3);
        for (GoodsTypeEnums value : values) {
            GoodsVo goodsVo = new GoodsVo();
            goodsVo.setGoodsType(value);
            goodsVo.setStatus("已上架");
            LambdaQueryWrapper<Goods> queryWrapper = buildGoodsWrapper(goodsVo, true);
            // 默认只展示6个数据
            queryWrapper.last("LIMIT 6");
            List<Goods> goods = baseMapper.selectList(queryWrapper);
            goods.forEach(item -> zoneGoodsIds.add(item.getGoodsId()));
            zoneGoods.put(value.getValue(), goods);
        }
        // 将数据进行缓存，以便于排除
        String key = goodsTypeEnums != null ? goodsTypeEnums.getValue() + "_" + CommonConstants.REDIS_KEY.ZONE_GOODS_ID : CommonConstants.REDIS_KEY.ZONE_GOODS_ID;
        redisCache.setCacheObject(key, zoneGoodsIds);
        return zoneGoods;
    }

    @Override
    public boolean isSameCycle(String oldCycleId, String newCycleId) {
        String[] oldCycleIds = StrUtil.split(oldCycleId, "-");
        String[] newCycleIds = StrUtil.split(newCycleId, "-");
        return StrUtil.equals(oldCycleIds[2], newCycleIds[2]);
    }

    @Override
    public Map<String, Integer> statisticTypeQuantity(GoodsVo vo) {
        return baseMapper.statisticTypeQuantity(GoodsTypeEnums.values(), buildGoodsWrapper(vo, false));
    }

    @Override
    public Map<String, Integer> statisticStatusQuantity(GoodsVo vo) {
        return baseMapper.statisticStatusQuantity(buildGoodsWrapper(vo, false));
    }

    @Override
    public Integer countGoodsByEnterpriseNo(String enterpriseNo) {
        if (StringUtils.isBlank(enterpriseNo)) {
            return 0;
        }
        return baseMapper.countByEnterpriseNo(enterpriseNo);
    }

    @Override
    public void relevancyEnterprise(Long id, String enterpriseNo, String enterpriseName) {
        if (id == null || StringUtils.isBlank(enterpriseNo)) {
            throw new ServiceException("参数异常");
        }
        Goods goods = Optional.ofNullable(getById(id))
                .orElseThrow(() -> new ServiceException("商品不存在"));
        if (enterpriseNo.equals(goods.getEnterpriseNo())) {
            throw new ServiceException("该商品已关联" + enterpriseName + "企业,不可重复操作");
        }
        if (StringUtils.isNotBlank(goods.getEnterpriseNo())) {
            throw new ServiceException("该商品已关联其他企业");
        }
        baseMapper.relevancyEnterprise(goods.getGoodsId(), enterpriseNo, enterpriseName);
    }

    @Override
    public List<Goods> selectUnRelevancyEnterpriseList(GoodsVo vo) {
        LambdaQueryWrapper<Goods> queryWrapper = buildGoodsWrapper(vo, true);
        queryWrapper.and(wrapper -> {
            wrapper.isNull(Goods::getEnterpriseNo).or().eq(Goods::getEnterpriseNo, "");
        });
        return baseMapper.selectList(queryWrapper);
    }

    @Override
    public List<Goods> selectListByEnterpriseNo(String enterpriseNo) {
        if (StringUtils.isBlank(enterpriseNo)){
            return new ArrayList<>();
        }
        return baseMapper.selectList(Wrappers.<Goods>lambdaQuery()
                .eq(Goods::getEnterpriseNo,enterpriseNo));
    }

    @Override
    public List<String> selectBrandListByEnterpriseNo(String enterpriseNo) {
        List<Goods> goodsList = selectListByEnterpriseNo(enterpriseNo);
        return goodsList.parallelStream()
                .map(Goods::getBrand)
                .filter(StringUtils::isNotBlank)
                .distinct()
                .collect(Collectors.toList());
    }
}

